/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds;

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.worlds.lua.Event;
import net.worlds.object.AbstractCharacter;
import net.worlds.object.Part;
import org.jbox2d.collision.shapes.Shape;
import org.jbox2d.common.Vec2D;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.ContactListener;
import org.jbox2d.dynamics.contacts.ContactPoint;
import org.jbox2d.dynamics.contacts.ContactResult;


public class XContactListener implements ContactListener{
    private ArrayList<Collision> collisions = new ArrayList<Collision>(WorldsSettings.MAX_OBJECTS);
    public void add(ContactPoint point) {
        final Shape s1 = point.shape1;
        final Shape s2 = point.shape2;
        final Body b1 = point.shape1.getBody();
        final Body b2 = point.shape2.getBody();
        if(b1.m_isExplosion)
        {
            b1.m_isExplosion = false;
            Main.runInMainThread(new Runnable()
            {

                public void run() {
                    b1.world.removeBody(b1);
                }
                
            });
        }
        else if(b2.m_isExplosion)
        {
            b2.m_isExplosion = false;
            Main.runInMainThread(new Runnable()
            {

                public void run() {
                    b2.world.removeBody(b2);
                }
                
            });
        }
        final Part p1 = s1.getUserData();
        final Part p2 = s2.getUserData();
        Vec2D pos = point.position;
        if(point.velocity != null)
        {
            double force = point.velocity.length();
            try
            {
                if(p1 != null)
                {
                    p1.applyCollisionForce(b2, pos, force);
                }
                if(p2 != null)
                {
                    p2.applyCollisionForce(b1, pos, force);
                }
            }
            catch(WorldsException ex)
            {
                throw new RuntimeException(ex);
            }
        }
        try {
            if (s1.isTerrain && s2.getUserData() != null && s2.getUserData().getParent() instanceof AbstractCharacter && ((AbstractCharacter) s2.getUserData().getParent()).isPlayer()) {
                Main.getLocalPlayer().isJumping = false;
            }
            else if(s2.isTerrain && s1.getUserData() != null && s1.getUserData().getParent() instanceof AbstractCharacter && ((AbstractCharacter) s1.getUserData().getParent()).isPlayer()) {
                Main.getLocalPlayer().isJumping = false;
            }
        } catch (WorldsException ex) {
            throw new RuntimeException(ex);
        }
        if(s1.isTerrain && p2 != null)
            p2.getEvent("TerrainCollided").fire(Event.NULL);
        if(s2.isTerrain && p1 != null)
            p1.getEvent("TerrainCollided").fire(Event.NULL);
        if(p1 == null || p2 == null)
            return;
        try {
            if(p1.getIntProp("Layer") != p2.getIntProp("Layer"))
                return;
        } catch (WorldsException ex) {
        }
        p1.onCollided(p2, new Vec2D(point.velocity));
        p2.onCollided(p1, new Vec2D(point.velocity));
    }

    public void persist(ContactPoint point) {
        final Shape s1 = point.shape1;
        final Shape s2 = point.shape2;
        final Body b1 = point.shape1.getBody();
        final Body b2 = point.shape2.getBody();
        Part p1 = s1.getUserData();
        Part p2 = s2.getUserData();
        if(p1 == null || p2 == null)
            return;
        p1.onPersisted(p2);
        p2.onPersisted(p1);
    }

    public void remove(ContactPoint point) {
        final Shape s1 = point.shape1;
        final Shape s2 = point.shape2;
        final Body b1 = point.shape1.getBody();
        final Body b2 = point.shape2.getBody();
        Part p1 = s1.getUserData();
        Part p2 = s2.getUserData();
        if(p1 != null && p2 != null)
        {
            p1.onUncollided(p2);
            p2.onUncollided(p1);
        }
    }

    public void result(ContactResult point) {

    }

    private class Collision {
        public Part p1;
        public Part p2;
        public long collideTime;
    }
}
